import os
import sys
import json
import yaml
import datetime
import platform
import psycopg2
import xmltodict
from collections import namedtuple
import xml.etree.ElementTree as ET


class DictToObject:
    def __init__(self, dictionary):
        for key, value in dictionary.items():
            if isinstance(value, dict):
                setattr(self, key, DictToObject(value))
            else:
                setattr(self, key, value)

def dict2Params(p):
    keys = p.keys()
    Param = namedtuple('Param', keys)
    return Param(**p)

def loadYaml(yaml_file='config.yaml', type='struct'):
    current_path = os.path.abspath(".")
    yaml_path = os.path.join(current_path, yaml_file)
    file = open(yaml_path, 'r', encoding="utf-8")
    file_data = file.read()
    file.close()
    if type == 'iterator':
        return yaml.load_all(file_data, Loader=yaml.FullLoader)
    else:
        return DictToObject(yaml.load(file_data, Loader=yaml.FullLoader))

def toastNotifier(title, message):
    platform = checkPlatform()
    if (platform == 'Windows'):
        from win10toast import ToastNotifier
        toaster = ToastNotifier()
        toaster.show_toast(title=title, msg=message, icon_path="f.ico", duration=10, threaded=True)
    elif (platform == 'MacOS'):
        from subprocess import call
        cmd = 'display notification \"' + message + '\" with title \"' + title + '\"' + ' sound name \"Frog\"'
        call(["osascript", "-e", cmd])
    else:
        pass


def checkPlatform():
    if sys.platform.startswith('win'):
        return 'Windows'
    elif sys.platform.startswith('darwin'):
        return 'MacOS'
    elif sys.platform.startswith('linux'):
        if 'Microsoft' in platform.release(): \
                return 'Windows Subsystem for Linux (WSL)'
        else:
            return 'Linux'
    else:
        return 'Unknown'


def param2object(p, dicts):
    if type(dicts) in [str, tuple, list, dict]:
        if type(dicts) is dict:
            keys = dicts.keys()
        elif type(dicts) is tuple:
            keys = list(dicts)
        elif type(dicts) is str:
            keys = [x.strip() for x in dicts.split(',')]
        else:
            keys = dicts
    Params = namedtuple('Params', keys)
    plist = list()
    if type(dicts) in [str, tuple, list, dict]:
        if type(p) is tuple:
            ps = list(p)
        elif type(p) is str:
            ps = [x.strip() for x in p.split(',')]
        elif type(p) is dict:
            for kk in keys:
                for k, v in p.items():
                    if kk == k:
                        plist.append(v)
        else:
            ps = p
        if len(keys) == len(ps):
            plist = ps
        else:
            for i in range(0, len(keys)):
                if i < len(ps):
                    plist.append(ps[i])
                else:
                    plist.append(None)
    return Params._make(plist)


def dbConnect(pgsql):
    return psycopg2.connect(
        database=pgsql.name,
        user=pgsql.user,
        password=pgsql.password,
        host=pgsql.address,
        port=pgsql.port
    )


def dbDisconnect(conn):
    conn.commit()
    conn.close()


def dict2obj(object):
    if isinstance(object, dict):
        return namedtuple(
            'struct', object.keys()
        )(
            *(dict2obj(val) for val in object.values())
        )
    elif isinstance(object, (tuple, list, set, frozenset)):
        return type(object)(dict2obj(_) for _ in object)
    else:
        return object


def getKeys(data):
    keysAll_list = []
    def getkeys(data):  # 遍历json所有key
        if (type(data) == type({})):
            keys = data.keys()
            for key in keys:
                value = data.get(key)
                if (type(value) != type({}) and type(value) != type([])):
                    keysAll_list.append(key)
                elif (type(value) == type({})):
                    keysAll_list.append(key)
                    getkeys(value)
                elif (type(value) == type([])):
                    keysAll_list.append(key)
                    for para in value:
                        if (type(para) == type({}) or type(para) == type([])):
                            getkeys(para)
                        else:
                            keysAll_list.append(para)

    getkeys(data)
    return keysAll_list


# 检测目标字段tagkey是否在data(json数据)中
def isExtend(data, tagkey):
    if (type(data) != type({})):
        print('please input a json!')
    else:
        key_list = getKeys(data)
        for key in key_list:
            if (key == tagkey):
                return True
    return False


def readJsonFile(jsonFile):
    data = False
    if os.path.isfile(jsonFile):
        with open(jsonFile, 'r', encoding='utf-8') as f:
            if os.path.getsize(jsonFile) != 0:
                data = dict2obj(json.load(f))
    return data


def writeJsonFile(jsonFile, jsonData):
    with open(jsonFile, 'w', encoding='utf-8') as f:
        json.dump(jsonData, f, ensure_ascii=False)
    return jsonData


# 获取当前时间
def showCurrentTime():
    now_time = datetime.datetime.now()
    return now_time.strftime('%yyyy-%MM-%dd dddd %H:%mm:%ss')


def readXML(filename):
    return ET.parse(filename)


def writeXML(etree, filename):
    # ET.indent(etree, space='    ')
    etree.write(filename, encoding="utf-8", xml_declaration=True)


def XML2Dict(etree, namespaces=False):
    string = ET.tostring(etree.getroot())
    if (namespaces):
        return xmltodict.parse(string, process_namespaces=True)
    else:
        return xmltodict.parse(string)


def Dict2XML(data):
    string = xmltodict.unparse(data, pretty=True)
    return ET.ElementTree(ET.fromstring(string))


def XML2DictFromFile(filename, namespaces=False):
    etree = readXML(filename)
    return XML2Dict(etree, namespaces)


def XML2ObjFromFile(filename, namespaces=False):
    etree = readXML(filename)
    edict = XML2Dict(etree, namespaces)
    return dict2obj(edict)


def Dict2XMLToFile(data, filename):
    etree = ET.ElementTree(Dict2XML(data))
    etree.write(filename, encoding="utf-8", xml_declaration=True)